import { Request, Response, NextFunction } from 'express';
import logger from '@utils/logger';
import Alert from '@database/models/Alert';
import Ticket from '@database/models/Ticket';
import dayjs from 'dayjs';

/**
 * Analytics Controller
 */
class AnalyticsController {
  /**
   * Get overall statistics
   */
  async getStatistics(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { startDate, endDate } = req.query;

      // 设置日期范围
      const start = startDate ? new Date(startDate as string) : dayjs().subtract(30, 'days').toDate();
      const end = endDate ? new Date(endDate as string) : new Date();

      // 获取告警统计
      const totalAlerts = await Alert.countDocuments({
        createdAt: { $gte: start, $lte: end }
      });

      const previousPeriodStart = dayjs(start).subtract(dayjs(end).diff(start, 'day'), 'days').toDate();
      const previousAlerts = await Alert.countDocuments({
        createdAt: { $gte: previousPeriodStart, $lt: start }
      });

      const alertsChange = previousAlerts > 0
        ? Math.round(((totalAlerts - previousAlerts) / previousAlerts) * 100)
        : 0;

      // 获取工单统计
      const totalTickets = await Ticket.countDocuments({
        createdAt: { $gte: start, $lte: end }
      });

      const previousTickets = await Ticket.countDocuments({
        createdAt: { $gte: previousPeriodStart, $lt: start }
      });

      const ticketsChange = previousTickets > 0
        ? Math.round(((totalTickets - previousTickets) / previousTickets) * 100)
        : 0;

      // 计算 MTTR (平均解决时间)
      const resolvedTickets = await Ticket.find({
        status: 'resolved',
        'resolution.resolvedAt': { $gte: start, $lte: end }
      });

      let totalResolutionTime = 0;
      resolvedTickets.forEach(ticket => {
        if (ticket.resolution?.resolvedAt) {
          const resolutionTime = dayjs(ticket.resolution.resolvedAt).diff(dayjs(ticket.createdAt), 'hour', true);
          totalResolutionTime += resolutionTime;
        }
      });

      const mttr = resolvedTickets.length > 0
        ? (totalResolutionTime / resolvedTickets.length).toFixed(1)
        : '0';

      // 计算 SLA 合规率
      const slaCompliantTickets = resolvedTickets.filter(ticket => {
        if (ticket.resolution?.resolvedAt) {
          const resolutionTime = dayjs(ticket.resolution.resolvedAt).diff(dayjs(ticket.createdAt), 'hour');
          // 根据优先级设置 SLA 标准
          const slaThreshold = ticket.priority === 'critical' ? 4 :
                              ticket.priority === 'high' ? 8 :
                              ticket.priority === 'medium' ? 24 : 48;
          return resolutionTime <= slaThreshold;
        }
        return false;
      });

      const slaCompliance = resolvedTickets.length > 0
        ? Math.round((slaCompliantTickets.length / resolvedTickets.length) * 100)
        : 100;

      res.status(200).json({
        success: true,
        data: {
          totalAlerts,
          alertsChange,
          totalTickets,
          ticketsChange,
          mttr: parseFloat(mttr),
          mttrChange: 12, // 可以后续计算与上期比较
          slaCompliance,
          slaChange: 3.2,
          period: {
            start: start.toISOString(),
            end: end.toISOString()
          }
        }
      });
    } catch (error) {
      logger.error('Failed to get analytics statistics:', error as Error);
      next(error);
    }
  }

  /**
   * 获取告警趋势数据
   */
  async getAlertTrend(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { period = 'week' } = req.query;

      let days = 7;
      if (period === 'month') days = 30;
      if (period === 'year') days = 365;

      const trendData = [];

      for (let i = days - 1; i >= 0; i--) {
        const date = dayjs().subtract(i, 'days');
        const startOfDay = date.startOf('day').toDate();
        const endOfDay = date.endOf('day').toDate();

        const alertCount = await Alert.countDocuments({
          createdAt: { $gte: startOfDay, $lte: endOfDay }
        });

        const ticketCount = await Ticket.countDocuments({
          createdAt: { $gte: startOfDay, $lte: endOfDay }
        });

        trendData.push({
          date: date.format('YYYY-MM-DD'),
          alerts: alertCount,
          tickets: ticketCount
        });
      }

      res.status(200).json({
        success: true,
        data: trendData
      });
    } catch (error) {
      logger.error('Failed to get alert trend:', error as Error);
      next(error);
    }
  }

  /**
   * 获取工单分布数据
   */
  async getTicketDistribution(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { period = 'week' } = req.query;

      let days = 7;
      if (period === 'month') days = 30;

      const distributionData = [];

      for (let i = days - 1; i >= 0; i--) {
        const date = dayjs().subtract(i, 'days');
        const startOfDay = date.startOf('day').toDate();
        const endOfDay = date.endOf('day').toDate();

        const open = await Ticket.countDocuments({
          createdAt: { $gte: startOfDay, $lte: endOfDay },
          status: 'open'
        });

        const inProgress = await Ticket.countDocuments({
          createdAt: { $gte: startOfDay, $lte: endOfDay },
          status: 'in_progress'
        });

        const resolved = await Ticket.countDocuments({
          createdAt: { $gte: startOfDay, $lte: endOfDay },
          status: 'resolved'
        });

        const closed = await Ticket.countDocuments({
          createdAt: { $gte: startOfDay, $lte: endOfDay },
          status: 'closed'
        });

        distributionData.push({
          date: date.format('YYYY-MM-DD'),
          open,
          inProgress,
          resolved,
          closed
        });
      }

      res.status(200).json({
        success: true,
        data: distributionData
      });
    } catch (error) {
      logger.error('Failed to get ticket distribution:', error as Error);
      next(error);
    }
  }

  /**
   * 获取告警严重程度统计
   */
  async getAlertSeverity(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { startDate, endDate } = req.query;

      const start = startDate ? new Date(startDate as string) : dayjs().subtract(30, 'days').toDate();
      const end = endDate ? new Date(endDate as string) : new Date();

      const severityData = await Alert.aggregate([
        {
          $match: {
            createdAt: { $gte: start, $lte: end }
          }
        },
        {
          $group: {
            _id: '$severity',
            count: { $sum: 1 }
          }
        }
      ]);

      const formattedData = severityData.map(item => ({
        severity: item._id,
        count: item.count
      }));

      res.status(200).json({
        success: true,
        data: formattedData
      });
    } catch (error) {
      logger.error('Failed to get alert severity:', error as Error);
      next(error);
    }
  }

  /**
   * 获取响应时间统计
   */
  async getResponseTime(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { period = 'week' } = req.query;

      let days = 7;
      if (period === 'month') days = 30;

      const responseTimeData = [];

      for (let i = days - 1; i >= 0; i--) {
        const date = dayjs().subtract(i, 'days');
        const startOfDay = date.startOf('day').toDate();
        const endOfDay = date.endOf('day').toDate();

        const tickets = await Ticket.find({
          createdAt: { $gte: startOfDay, $lte: endOfDay },
          status: { $in: ['resolved', 'closed'] },
          'resolution.resolvedAt': { $exists: true }
        });

        let avgResponseTime = 0;
        if (tickets.length > 0) {
          const totalTime = tickets.reduce((sum, ticket) => {
            if (ticket.resolution?.resolvedAt) {
              return sum + dayjs(ticket.resolution.resolvedAt).diff(dayjs(ticket.createdAt), 'hour', true);
            }
            return sum;
          }, 0);
          avgResponseTime = totalTime / tickets.length;
        }

        responseTimeData.push({
          date: date.format('YYYY-MM-DD'),
          avgResponseTime: Math.round(avgResponseTime * 10) / 10
        });
      }

      res.status(200).json({
        success: true,
        data: responseTimeData
      });
    } catch (error) {
      logger.error('Failed to get response time:', error as Error);
      next(error);
    }
  }

  /**
   * 获取性能报告
   */
  async getPerformanceReport(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { startDate, endDate } = req.query;

      const start = startDate ? new Date(startDate as string) : dayjs().subtract(30, 'days').toDate();
      const end = endDate ? new Date(endDate as string) : new Date();

      // 获取所有已解决工单
      const resolvedTickets = await Ticket.find({
        status: { $in: ['resolved', 'closed'] },
        'resolution.resolvedAt': { $gte: start, $lte: end }
      });

      // 计算平均响应时间
      let totalResponseTime = 0;
      resolvedTickets.forEach(ticket => {
        if (ticket.resolution?.resolvedAt) {
          totalResponseTime += dayjs(ticket.resolution.resolvedAt).diff(dayjs(ticket.createdAt), 'minute');
        }
      });
      const avgResponseTime = resolvedTickets.length > 0
        ? (totalResponseTime / resolvedTickets.length).toFixed(1)
        : '0';

      // 首次响应 SLA
      const firstResponseTickets = resolvedTickets.filter(ticket => {
        if (ticket.resolution?.resolvedAt) {
          const responseTime = dayjs(ticket.resolution.resolvedAt).diff(dayjs(ticket.createdAt), 'hour');
          return responseTime <= 1; // 1小时内首次响应
        }
        return false;
      });
      const firstResponseSLA = resolvedTickets.length > 0
        ? ((firstResponseTickets.length / resolvedTickets.length) * 100).toFixed(1)
        : '0';

      // 解决率
      const totalTickets = await Ticket.countDocuments({
        createdAt: { $gte: start, $lte: end }
      });
      const resolutionRate = totalTickets > 0
        ? ((resolvedTickets.length / totalTickets) * 100).toFixed(1)
        : '0';

      res.status(200).json({
        success: true,
        data: {
          avgResponseTime: parseFloat(avgResponseTime),
          firstResponseSLA: parseFloat(firstResponseSLA),
          resolutionRate: parseFloat(resolutionRate),
          totalTickets,
          resolvedTickets: resolvedTickets.length
        }
      });
    } catch (error) {
      logger.error('Failed to get performance report:', error as Error);
      next(error);
    }
  }
}

export default new AnalyticsController();
